THE AMIGANET BLITZ BASIC FAQ
SPEEED OPTIMIZATIONS
As you know, there are many ways to obtain the same result, you can do an
easy to read program, but not very fast, or an incomprehensible and faster
one...
Here are my tests: Using the "ticks" commands i read the elapsed time to
accomplish to the same task, but in differen ways. The faster one will be
used! :)
FAST PRINT
Original message by Lynn Jennings
Printing things takes a very long time. First I'll briefly try to
explain why, then I'll try to be helpful and offer some suggestions on
speeding your code up.
Suppose I want to do this:
BitmapOutput 0
Print "Score: "+str$(Score)
What does this involve?
First, the string to be printed must be generated. Basically
this involves:
- Get the first bit ("Score: ")
- Use a routine that converts the variable (Score) into a string of characters that represents the value of the variable. For example, the number 10 would be converted from $0A to $31 $30 $00.
- Create a third string by tacking the string from (2) to the end of the string from (1).
Now that it knows what to print, it has to print it. This
involves:
- Start at the first character of the string to print
- Is this the end of the string? If yes, then quit.
- Use the ASCII code of the current character to look up what shape we are supposed to plot (using the current font).
- Use the blitter to blast the character onto the screen at the current cursor position, being careful not to draw outside of the actual screen.
- Increment the cursor position and get the next character in the string.
- Go to step (2) and continue until the print is finished.
As you can see, that's a LOT of steps to go through for each Print you use.
How can you ease the situation?
Here are strategies you can use alone or in combination to
speed up the printing routine:
[1]
Only print what you have to; print constant strings once.
For example, if you are using code like this:
.main
Repeat
Gosub Update
Forever
Update:
Locate X,Y
NPrint "Player One: "+str$(Score(0))
Print "Player Two: "+str$(Score(1))
Return
Change your code to this:
Locate X,Y
NPrint "Player One: "
Print "Player Two: "
.main
Repeat
Gosub Update
Forever
Update:
Locate X+12,Y :Print str$(Score(0))
Locate X+12,Y+1:Print str$(Score(1))
Return
[2]
Only print things when they change.
Use copies of variables to detect when they have changed.
For example, if you use code like this:
...
If HitTarget Then Score+100 ; 100 points for hitting target
...
Print str$(Score)
Change your code to this:
...
If HitTarget Then Score+100 ; 100 points for hitting target
...
If OldScore<>Score Then Print str$(Score):OldScore=Score
[3]
Don't print everything every time through. If you intend to update the
screen at 25 frames per second or so, you don't need to update scores
that often! Every 1/6 second or thereabouts is usually more than adequate.
Divide your screen updates into a number of subjobs, and only do one subjob
each time the Update routine is called. For example, if you have code like
this:
Update:
Print str$(Score(0)) ; Update player 1's score
Print str$(Score(1)) ; Update player 2's score
Return
Change it to look like this:
Update:
UpdateFlag=1-UpdateFlag ; this var will toggle between 0`and 1
If UpdateFlag
Print str$(Score(0)) ; Update player 1's score
Else
Locate X,Y+1
Print str$(Score(1)) ; Update player 2's score
EndIf
Return
For more than two subgroups, of course, use a normal counter:
n=n+1:if n>#NUMBER_OF_SUBGROUPS_PLUS_ONE then n=0
If you use the above trick to get a vaule for a two-player game (as in
Score(0) and Score(1)), and you have to update a LOT (and I mean a LOT) of
things in arrays (eg. X(0/1), Y(0/1), TimeLeft(0/1), etc., etc.), then it
will be faster to use the following:
.main
Repeat
Player=1-Player
if Player=0
Gosub HandlePlayerOne
else
Gosub HandlePlayerTwo
endif
Forever
HandlePlayerOne:
Print Score(0):Return
HandlePlayerTwo:
Print Score(1):Return
Again, this is only an economical tradeoff between speed and code size when
you are updating a LOT of things.
Hope you find the above useful.
Go to top of page.
RANDOM NUMBERS GENERATOR
Original message by Andrea Doimo
In games makeing the RND function is used for many purposes, so is very
important to find the fastest way to take decisions.
I was used with other languages to use the "integer" version, but with
Blitz, it's better to use the first solution.
DEFTYPE .w
ResetTimer
;First test. Fixed point numbers.
For n=1 To 25000
If Rnd>.5 Then
Next
t1.l=Timer
;Second test. Integer numbers.
ResetTimer
For n=1 To 25000
If Rnd(100)>50 Then
Next
t2.l=Timer
NPrint t1
NPrint t2
MouseWait
Go to top of page.
DOUBLING A VARIABLE CONTENT
Original message by Andrea Doimo
I've found three ways to double a variable: Using the classic "*"
operator, left shifting the bytes, or adding the variable to itself.
The last one is the fastest, but in many ways using the shifting is easyer.
Shifting is the best choose when you've to mutiply by powers of 2, like
4,8,16,32 and so on...
DEFTYPE .w
;First Test. * operator
ResetTimer
For n.l=1 To 500000
a=n*2
Next
t1.l=Timer
;Second test. Bytes shifting
ResetTimer
For n.l=1 To 500000
a=n ASL 1
Next
t2.l=Timer
;Thirth test. Adding to itself.
ResetTimer
For n.l=1 To 500000
a=n+n
Next
t3.l=Timer
NPrint t1
NPrint t2
NPrint t3
MouseWait
End
Go to top of page.